//
//  ADKit.m
//  ADKit
//
//  Created by duzexu on 2017/12/8.
//

#import "ADKit.h"
#import "ADKitHeaders.h"
#import "STFAutoLayoutDebugManager.h"

#define ADApplicationVersionKey @"ADApplicationVersionKey"
#define ADApplicationFirstLaunchKey @"ADApplicationFirstLaunchKey"

#define ADApplicationCrashKey @"ADApplicationCrashKey"
#define ADApplicationCrashCountKey @"ADApplicationCrashCountKey"

static char AD_Delegate_Version_Key;
static char AD_Delegate_FirstLaunch_Key;
static char AD_Delegate_Stack_Key;
static char AD_Delegate_Service_Key;

@implementation ADKit

+ (void)load {
    Class cls = NSClassFromString(@"AppDelegate");
    [cls aspect_hookSelector:@selector(application:didFinishLaunchingWithOptions:)
                 withOptions:AspectPositionAfter
                  usingBlock:^(id<AspectInfo> aspectInfo,UIApplication *application,NSDictionary *launchOptions) {
                      [ADKit ad_configureAfterLaunch];
                  }
                       error:nil];
}

+ (void)ad_configureAfterLaunch {
    NSString *version = [[NSUserDefaults standardUserDefaults] valueForKey:ADApplicationVersionKey];
    BOOL isNewVersion = ![version isEqualToString:[UIApplication sharedApplication].appVersion];
    if (isNewVersion) {
        [NSFileManager ad_removeFile:ADViewModel.viewModelCachePath];
    }
    [self.appDelegate setAssociateWeakValue:@(isNewVersion) withKey:&AD_Delegate_Version_Key];
    BOOL isFirstLaunch = ![[NSUserDefaults standardUserDefaults] boolForKey:ADApplicationFirstLaunchKey];
    [self.appDelegate setAssociateWeakValue:@(isFirstLaunch) withKey:&AD_Delegate_FirstLaunch_Key];
#if !DEBUG
    BOOL isCrash = [[NSUserDefaults standardUserDefaults] boolForKey:ADApplicationCrashKey];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:ADApplicationCrashKey];
    if (isCrash) {
        NSInteger crashCount = [[NSUserDefaults standardUserDefaults] integerForKey:ADApplicationCrashCountKey];
        crashCount++;
        if (crashCount >= 3) {
            if ([self.appDelegate respondsToSelector:@selector(ad_crashProtect)]) {
                [self.appDelegate performSelector:@selector(ad_crashProtect)];
            }
            [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:ADApplicationCrashCountKey];
        }else{
            [[NSUserDefaults standardUserDefaults] setInteger:crashCount forKey:ADApplicationCrashCountKey];
        }
    }
#endif
    
    ADViewModelServiceImp *services = [[ADViewModelServiceImp alloc] init];
    [self.appDelegate setAssociateValue:services withKey:&AD_Delegate_Service_Key];
    ADNavigationControllerStack *stack = [[ADNavigationControllerStack alloc] initWithServices:services window:[self mainWindow]];
    [self.appDelegate setAssociateValue:stack withKey:&AD_Delegate_Stack_Key];
    
    UIViewController *root = [self mainWindow].rootViewController;
    if ([root isKindOfClass:UINavigationController.class]) {
        [[self navControllerStack] pushNavigationController:(UINavigationController*)root];
    }
    
    //add noti delegate method
    __addMethod([ADKit.appDelegate class], @selector(application:didReceiveRemoteNotification:), [self methodForSelector:@selector(application:didReceiveRemoteNotification:)]);
    __addMethod([ADKit.appDelegate class], @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:), [self methodForSelector:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]);
    
    if ([self.appDelegate conformsToProtocol:@protocol(ADConfigurationDelegate)]) {
        if ([self.appDelegate respondsToSelector:@selector(ad_systemConfiguration)]) {
            [self.appDelegate performSelector:@selector(ad_systemConfiguration)];
        }
        if ([self.appDelegate respondsToSelector:@selector(ad_thirdConfiguration)]) {
            [self.appDelegate performSelector:@selector(ad_thirdConfiguration)];
        }
        if ([self.appDelegate respondsToSelector:@selector(ad_dataBaseConfiguration)]) {
            [self.appDelegate performSelector:@selector(ad_dataBaseConfiguration)];
        }
        if ([self.appDelegate respondsToSelector:@selector(ad_otherConfiguration)]) {
            [self.appDelegate performSelector:@selector(ad_otherConfiguration)];
        }
    }
    
    [self _configureKeyboardManager];
    
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:ADSwitchRootViewControllerNotification object:nil] subscribeNext:^(NSNotification * note) {
        ADViewModel *model = note.object[ADSwitchRootViewControllerViewModelKey];
        [ADKit.services resetRootViewModel:model];
    }];
    
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:ADApplicationCrashKey];
        [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:ADApplicationCrashCountKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }];
    
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationWillTerminateNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:ADApplicationCrashKey];
        [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:ADApplicationCrashCountKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }];
    
#if DEBUG
    [self _configDebugModelTools];
#endif
    
    [[NSUserDefaults standardUserDefaults] setValue:[UIApplication sharedApplication].appVersion forKey:ADApplicationVersionKey];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:ADApplicationFirstLaunchKey];
    
    [[NSUserDefaults standardUserDefaults] synchronize];
}

+ (void)_configureKeyboardManager {
    IQKeyboardManager.sharedManager.enable = YES;
    IQKeyboardManager.sharedManager.enableAutoToolbar = NO;
    IQKeyboardManager.sharedManager.shouldResignOnTouchOutside = YES;
}

+ (void)_configDebugModelTools {
    [STFAutoLayoutDebugManager defaultManger].enableDebugMode = YES;
#if ENABLE_GodEye
    Configuration *config = [Configuration new];
    [GodEye makeEyeWith:[self mainWindow] configuration:config];
#endif
}

+ (id)appDelegate {
    return [UIApplication sharedApplication].delegate;
}

+ (UIViewController *)rootVC {
    return [self.appDelegate window].rootViewController;
}

+ (UIWindow *)mainWindow {
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    if (window) {
        return window;
    }
    if ([self.appDelegate respondsToSelector:@selector(window)]) {
        return [self.appDelegate window];
    }
    return nil;
}

+ (BOOL)isNewVersion {
    return [[self.appDelegate getAssociatedValueForKey:&AD_Delegate_Version_Key] boolValue];
}

+ (BOOL)isFirstLaunch {
    return [[self.appDelegate getAssociatedValueForKey:&AD_Delegate_FirstLaunch_Key] boolValue];
}

+ (ADViewModelServiceImp *)services {
    return [self.appDelegate getAssociatedValueForKey:&AD_Delegate_Service_Key];
}

+ (ADNavigationControllerStack *)navControllerStack {
    return [self.appDelegate getAssociatedValueForKey:&AD_Delegate_Stack_Key];
}

+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if ([ADKit.appDelegate respondsToSelector:@selector(ad_handleRemoteNotification:)]) {
        [ADKit.appDelegate ad_handleRemoteNotification:userInfo];
    }
}

+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    if ([ADKit.appDelegate respondsToSelector:@selector(ad_handleRemoteNotification:)]) {
        [ADKit.appDelegate ad_handleRemoteNotification:userInfo];
    }
    completionHandler(UIBackgroundFetchResultNewData);
}

@end
